package com.bangyu.monitor.modular.system.biz;

import cn.hutool.core.date.DateUtil;
import com.bangyu.monitor.core.common.constant.Const;
import com.bangyu.monitor.core.common.constant.ConstantEnum;
import com.bangyu.monitor.core.shiro.ShiroKit;
import com.bangyu.monitor.core.util.InfluxDbUtil;
import com.bangyu.monitor.core.util.ListUtils;
import com.bangyu.monitor.modular.system.entity.*;
import com.bangyu.monitor.modular.system.service.*;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateFormatUtils;
import org.influxdb.dto.QueryResult;
import org.joda.time.DateTime;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.*;

/**
 * @Auther: zhangxue
 * @Date: 19/4/26 12:55
 * @Description:
 */
@Service
@Slf4j
public class DataViewBiz {

    @Autowired
    private OriginalDataService originalDataService;

    @Autowired
    private WeightPayloadService weightPayloadService;

    @Autowired
    private PayloadService payloadService;

    @Autowired
    private StaticStandDisplaymentService staticStandDisplaymentService;

    @Autowired
    private BridgeService bridgeService;

    @Autowired
    private RiskService riskService;

    @Autowired
    private MaintainRecordService maintainRecordService;

    @Autowired
    private BridgeBiz bridgeBiz;

    @Autowired
    private WeightPayloadRecoverService payloadRecoverService;

    /**
     * 2小时的实时数据
     * @return
     */
    public Object queryRealTimeData(String beamNo,Long startTime){
        long t1 = System.currentTimeMillis();
        Map map = Maps.newHashMap();
        //List<RealtimeOriginalDto> originalDatas = originalDataService.queryByTimeLimit(beamNo,DateFormatUtils.format(new Date(),"yyyyMMdd"),startTime);
        String sql = String.format("select time,beam_no,temperature,static_displayment,bend_value from %s.%s where beam_no = '%s' and time > %d order by time asc",
                Const.INFLUX_RETENTION_POLICY_ONE_HOUR,Const.INFLUX_TABLE_ORIGINAL_DATA,beamNo,startTime*Const.MS_NS);
        System.out.println("sql :"+sql);
        QueryResult queryResult = InfluxDbUtil.query(Const.INFLUX_DATABASE,sql
                );
        if(!queryResult.hasError() && CollectionUtils.isNotEmpty(queryResult.getResults())){
            QueryResult.Result result = queryResult.getResults().get(0);
            List<QueryResult.Series> seriesList = result.getSeries();
            if(CollectionUtils.isNotEmpty(seriesList)){
                QueryResult.Series series = seriesList.get(0);
                List<List<Object>> values = series.getValues();
                map.put("temperature",Lists.newArrayList());
                map.put("staticDesplayment",Lists.newArrayList());
                map.put("bendValue",Lists.newArrayList());
                map.put("receiveTime",Lists.newArrayList());
                for(int i=0;i<values.size()-1;i++ ){

                    List<Object> pre = values.get(i);
                    List<Object> next = values.get(i+1);
                    //如果两个数据之间的间隙大于50毫秒,补上空值
                    long periodTime = parseDate(next.get(0).toString())-parseDate(pre.get(0).toString());
                    //每隔50毫秒插入一个数据，count 为pre与next中间需要插入的数据
                    long count = (periodTime/50);
                    if(periodTime<=50){
                        replenishData(pre,1,map);
                    }else{
                        List temp = new ArrayList();
                        temp.add(pre.get(0));
                        replenishData(temp,count,map);
                    }

                }
                //把最后一条数据加上
                replenishData(values.get(values.size()-1),1,map);
            }

        }

        long t2 = System.currentTimeMillis();
        log.info("queryRealTimeData 发放执行时间:{}",t2-t1);


        return map;
    }

    private void replenishData(List data,long count,Map<String,List> container){
        if(count >0){
            Long receiveDate = parseDate(data.get(0).toString());
            Double temperature = data.size()==1||data.get(2)==null?null:(double)data.get(2);
            Double standBend = data.size()==1||data.get(3)==null?null:(double)data.get(3);
            Double bendValue = data.size()==1||data.get(4)==null?null:(double)data.get(4);
            List temperatureList = container.get("temperature");
            List staticDesplaymentList = container.get("staticDesplayment");
            List bendValueList = container.get("bendValue");
            List receiveList = container.get("receiveTime");
            for(int i=0;i<count;i++){
                receiveDate = receiveDate+50;
                bendValueList.add(doubleScle(bendValue));

                staticDesplaymentList.add(doubleScle(standBend));

                temperatureList.add(doubleScle(temperature));
                receiveList.add(receiveDate);

//                container.get("temperature").add(doubleScle(temperature));
//                container.get("standBendValue").add(doubleScle(standBend));
//                container.get("bendValue").add(doubleScle(bendValue));
//                container.get("time").add(receiveDate);

            }
        }
    }

    /**
     * 突发荷载预警数据(重型荷载的恢复时间)
     * @return
     */
    public Map payloadRecoverQuery(String beamNo,Integer startDate,Integer endDate){
        List<WeightPayloadRecover> payloads = payloadRecoverService.getByBeamNoAndDateLimit(beamNo,startDate,endDate);

        Map result = Maps.newHashMap();
        if(CollectionUtils.isNotEmpty(payloads)){
            List l1 = Lists.newArrayList();//6秒内恢复
            List l2 = Lists.newArrayList();//6-60秒内恢复
            List l3 = Lists.newArrayList();//一分钟-12小时内恢复
            List l4 = Lists.newArrayList();//大于12小时恢复

            for(WeightPayloadRecover payload:payloads){
                Integer recoverType = payload.getRecoverType();
                long time = payload.getReceiveTime();
                Float bend = payload.getBendValue();
                switch (recoverType){
                case 1://6秒内恢复
                    List l11 = Lists.newArrayList();
                    l11.add(time);
                    l11.add(bend);
                    l1.add(l11);
                    break;
                case 2://6-60秒内恢复
                    List l22 = Lists.newArrayList();
                    l22.add(time);
                    l22.add(bend);
                    l2.add(l22);
                    break;
                case 3://1分钟-12小时内恢复
                    List l33 = Lists.newArrayList();
                    l33.add(time);
                    l33.add(bend);
                    l3.add(l33);
                    break;
                case 4://大于12小时恢复
                    List l44 = Lists.newArrayList();
                    l44.add(time);
                    l44.add(bend);
                    l4.add(l44);
                    break;
                }
            }
            result.put("6Second",l1);
            result.put("6To1Min",l2);
            result.put("1MinTo12Hour",l3);
            result.put("morethan12Hour",l4);
        }
        return result;


    }

    /**
     * 获取梁的重型荷载和轻型荷载数量
     * @param beam
     * @param dateStart
     * @param dateEnd
     * @return
     */
    public Map queryCountByPayloadType(String beam,Integer dateStart,Integer dateEnd){
        Map result = Maps.newHashMap();
        result.put(Const.PAYLOAD_TYPE_LIGHT.toString(),0);
        result.put(Const.PAYLOAD_TYPE_HEAVY.toString(),0);

        String sql1 = "select count(v0) from light_payload where beam_no =  '"+beam+"'";
        String sql2 = "select count(v0) from weight_payload where beam_no =  '"+beam+"'";

        if(dateStart != null){
            long startDateLong = DateUtil.parse(dateStart.toString(),"yyyyMMdd").getTime()*Const.MS_NS;
            sql1 = sql1+ "and time >"+startDateLong;
            sql2 = sql2+ "and time >"+startDateLong;
        }
        if(dateEnd != null){
            long endDateLong = DateUtil.parse(dateEnd.toString(),"yyyyMMdd").getTime()*Const.MS_NS;
            sql1 = sql1+ " and time <"+endDateLong;
            sql2 = sql2+ " and time <"+endDateLong;
        }

        QueryResult queryResult1 = InfluxDbUtil.query(Const.INFLUX_DATABASE,sql1);
        QueryResult queryResult2 = InfluxDbUtil.query(Const.INFLUX_DATABASE,sql2);


        if(queryResult1 != null && queryResult1.getResults() != null){
            QueryResult.Result qResult1 = queryResult1.getResults().get(0);
            if(qResult1.getSeries() != null){
                List<List<Object>> lists1 = qResult1.getSeries().get(0).getValues();
                Double d1 = (Double)lists1.get(0).get(1);
                result.put(Const.PAYLOAD_TYPE_LIGHT.toString(),d1.longValue());
            }
        }

        if(queryResult2 != null && queryResult2.getResults() != null){
            QueryResult.Result qResult2 = queryResult2.getResults().get(0);
            if(qResult2.getSeries() != null){
                List<List<Object>> lists2 = qResult2.getSeries().get(0).getValues();
                Double d2 = (Double)lists2.get(0).get(1);
                result.put(Const.PAYLOAD_TYPE_HEAVY.toString(),d2.longValue());
            }
        }
        return result;
    }


    /**
     * 极限预警数据(重型荷载每种极限界别的数量)
     * @param beamNo
     * @param startDate
     * @param endDate
     * @return
     */
    public Map extremityCount(String beamNo,Integer startDate,Integer endDate){
        Map result = Maps.newHashMap();
        result.put(Const.EXTREMITY_RESERVE.toString(),0);//储备
        result.put(Const.EXTREMITY_SAFE.toString(),0);//安全
        result.put(Const.EXTREMITY_WARN.toString(),0);//预警
        result.put(Const.EXTREMITY_ALARM.toString(),0);//报警


        String sql = "select count(v0) from weight_payload where  beam_no='"+beamNo+"' group by extremityLevel ";

        if(startDate != null){
            long startDateLong = DateUtil.parse(startDate.toString(),"yyyyMMdd").getTime()*Const.MS_NS;
            sql = sql+ "and time >"+startDateLong;
        }
        if(endDate != null){
            long endDateLong = DateUtil.parse(endDate.toString(),"yyyyMMdd").getTime()*Const.MS_NS;
            sql = sql+ " and time <"+endDateLong;
        }

        QueryResult queryResult = InfluxDbUtil.query(Const.INFLUX_DATABASE,sql);


        if(queryResult != null && queryResult.getResults() != null){
            QueryResult.Result qResult1 = queryResult.getResults().get(0);
            if(qResult1.getSeries() != null){
                for(QueryResult.Series series:qResult1.getSeries()){
                    String tag = series.getTags().get("extremityLevel");
                    Object count = series.getValues().get(0).get(1);
                    if(count != null){
                        int count_ = ((Double)count).intValue();
                        if(Const.EXTREMITY_RESERVE.toString().equalsIgnoreCase(tag) ){
                            result.put(Const.EXTREMITY_RESERVE.toString(),count_);
                        }else if(Const.EXTREMITY_SAFE.toString().equalsIgnoreCase(tag)){
                            result.put(Const.EXTREMITY_SAFE.toString(),count_);//安全
                        } else if(Const.EXTREMITY_WARN.toString().equalsIgnoreCase(tag)){
                            result.put(Const.EXTREMITY_WARN.toString(),count_);
                        } else if(Const.EXTREMITY_ALARM.toString().equalsIgnoreCase(tag)){
                            result.put(Const.EXTREMITY_ALARM.toString(),count_);
                        }
                    }

                }
            }
        }

        return result;
    }

    /**
     * 获取每一年每天的静态数据并格式化
     * @param beamNo
     * @return {
     * 	"keys":["04-01","04-02","04-03"],
     * 	"data":[
     * 		{
     * 		"year":"2015",
     * 		"data":[0.4,0.5,0.6]
     * 	}
     * 	]
     * }
     */
    public Map queryStaticStandValueByYear(String beamNo){
        List<StaticStandDisplayment> standBends = staticStandDisplaymentService.queryByBeamNo(beamNo);

        Map result = Maps.newHashMap();


        if(CollectionUtils.isNotEmpty(standBends)){
            //把日期筛选出来作为图标的x轴坐标
            Set dateSet = Sets.newTreeSet();
            for(StaticStandDisplayment bend:standBends){
                String date = bend.getDate();
                dateSet.add(date);
            }
            //日期正序排列
            List<String> dateList = Lists.newArrayList(dateSet);
            Collections.sort(dateList);
            result.put("keys",dateList);


            //按年分组
            Map<String,List<StaticStandDisplayment>> groups = ListUtils.group(standBends,"year");
            //年份正序排列
            Set yearSet = groups.keySet();
            List<String> yearList = Lists.newArrayList(yearSet);
            Collections.sort(yearList);


            List yearsData = Lists.newArrayList();
            for(String year:yearList){//年份
                List yearData = Lists.newArrayList();
                List<StaticStandDisplayment> yearDataList = groups.get(year);//某一年的静态数据
                //把该年的静态数据转成map，日期作为key
                Map<String,StaticStandDisplayment> dateMap = ListUtils.toMap(yearDataList,"date");
                for(String date:dateList){//所有日期
                    StaticStandDisplayment bend = dateMap.get(date);
                    yearData.add(bend==null?"":bend.getZero());

                }
                Map t = Maps.newHashMap();
                t.put("year",year);
                t.put("data",yearData);
                yearsData.add(t);
            }
            result.put("data",yearsData);


        }
        return result;
    }

    public MonitorInfoSummary monitorInfoSummary(Integer startDate,Integer endDate){



        MonitorInfoSummary summary = new MonitorInfoSummary();

        summary.setCustomerName(ShiroKit.getUser().getName());

        List<Bridge> bridges = bridgeBiz.listByPermission(null);

        List<Long> bridgeIds = Lists.newArrayList();

        if(CollectionUtils.isNotEmpty(bridges)){
            for(Bridge bridge:bridges){
                bridgeIds.add(bridge.getBridgeId());
            }
            //管理桥梁数量
            summary.setManagerCount(bridges.size());
            //已安装设备的桥梁
            List<Bridge> bridgeWithDevice = (List)CollectionUtils.select(bridges, new Predicate() {
                @Override public boolean evaluate(Object o) {
                    Bridge bridge = (Bridge)o;
                    return StringUtils.isNotBlank(bridge.getDeviceNo());
                }
            });
            summary.setMonitorCount(CollectionUtils.isNotEmpty(bridgeWithDevice)?bridgeWithDevice.size():0);
            summary.cacuRate();

            summary.setWarnCount(riskService.bridgeCountOfRisk(bridgeIds,ConstantEnum.RiskLevel.RISK_LEVEL_WARN.getKey(),startDate,endDate));
            summary.setAlarmCount(riskService.bridgeCountOfRisk(bridgeIds,ConstantEnum.RiskLevel.RISK_LEVEL_ALARM.getKey(),startDate,endDate));

            summary.setMaintainCount(maintainRecordService.bridgeCountOfMaintain(bridgeIds,startDate,endDate));


        }
        return summary;
    }

    private long parseDate(String str){
        return new DateTime(str).getMillis();
    }
    private Float doubleScle(Double d){
        if(d != null){
            return new BigDecimal(d).setScale(2, BigDecimal.ROUND_HALF_UP).floatValue();
        }
        return null;
    }

    public static void main(String[] args) {
        String aa = "2019-06-27T15:13:21.05Z";
//        long a = DateUtil.parse(aa,"yyyy-MM-ddTHH:mm:ss.SSZ").getTime();

        DateTime dateTime = new DateTime(aa);

        System.out.println(dateTime.getMillis());
        System.out.println();

    }

}
